#ifndef RX_GEORASTER
#define RX_GEORASTER

#include <osg/Shape>
#include "Extent.h"

using namespace rxtiler;

class GeoRaster
{
public:
    GeoRaster(void){_raster = 0;}
    GeoRaster(osg::HeightField* r,Extent& e){
        _raster = r;
        _extent = e;
    }

    inline float getGeoVal(double lon,double lat)
    {
        //函数内部不做范围判断
        //请在外部保证
        double rx = (lon - this->_extent.left ) / (_extent.right - _extent.left);
        double r = lat - _extent.bottom;
        double ry = r / (_extent.top - _extent.bottom);
        //int x = (_raster->x()-1) * rx + 0.5;
        //int y = (_raster->y()-1) * ry + 0.5;

        //return _raster->getVal<T>(x,y,z);

        int x = _raster->getNumColumns() - 1;
        int y = _raster->getNumRows() - 1;
        rx = x * rx;
        ry = y * ry;

        int it = (int)rx;
        int is = (int)ry;
        int it1 = it < x ? it + 1 : it;
        int is1 = is < y ? is + 1 : is;
//            int it1 = it + 1;
//            int is1 = is + 1;
        float v00 = _raster->getHeight(it,is);
        float v01 = _raster->getHeight(it,is1);
        float v10 = _raster->getHeight(it1,is);
        float v11 = _raster->getHeight(it1,is1);
//        T v00 =  _raster->getVal<T>(it,is,z);
//        T v01 =  _raster->getVal<T>(it,is1,z);
//        T v10 =  _raster->getVal<T>(it1,is,z);
//        T v11 =  _raster->getVal<T>(it1,is1,z);

        double dx = rx - it;
        double dy = ry - is;

        return v00 * (1- dx)*(1-dy) + v10 * (1-dy)*dx + v11 * dx * dy + v01 * dy * (1-dx);
    }

    void mapfrom( GeoRaster& grst )
    {
        int ax = _raster->getNumColumns() - 1;
        int ay = _raster->getNumRows() - 1;
        for (int y = 0; y <= ay;++y)
        {
            double lat =  (double)y / ay  * (_extent.top - _extent.bottom);
            lat =  _extent.bottom + lat;
            if (grst._extent.containy(lat)){
                for (int x = 0; x <= ax;++x)
                {
                    double lon = (double)x / ax * (_extent.right - _extent.left) + _extent.left;
                    if (grst._extent.containx(lon))
                    {
                        float v = grst.getGeoVal(lon,lat);
                        this->_raster->setHeight(x,y,v);
                    }
                }

            }
        }
    }

protected:
    Extent _extent;
    osg::HeightField* _raster;
//		bool _lefttop;
};

inline void mapRaster(osg::HeightField *in, Extent& inext, osg::HeightField *out, Extent &outext){
    if(!in || !out){
        return;
    }
    GeoRaster gr1(in,inext);
    GeoRaster gr2(out,outext);
    gr2.mapfrom(gr1);
}

#endif

